#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>						/*包含socket()/bind()*/
#include <netinet/in.h>						/*包含struct sockaddr_in*/
#include <string.h>							/*包含memset()*/
#include <fcntl.h>
#include <sys/time.h>
#include <sys/stat.h>

#define PORT_SERV 8888						/*服务器端口*/
#define BUFF_LEN 256							/*缓冲区大小*/
#define PACKET_MAX_SEQ 1000
#define LENGTH 1024
#define SEND_LENGTH LENGTH+12
#define NUM_DATA 100

char buff_send[SEND_LENGTH];


/**
 * 包装数据
 * 
 * @param index: 包索引值
 * @param flag: 为0表示其为中间包，为1表示为结束包，大于1表示其长度
 * @param userId: 用户id
 * @param data: 字符串数据指针
*/
void wrapper_data(int index, int flag, int userId, char * data)
{
	*((int*)&buff_send[0])=htonl(index);
	*((int*)&buff_send[4])=htonl(flag);
	*((int*)&buff_send[8])=htonl(userId);
	// sizeof 包括结束运算符，计算的是分配内存长度
	memcpy(&buff_send[12], data,LENGTH);
}

/**
 * 发送时先发送一个index为0的包，传输文件长度
 * 然后服务端动态分配内存
*/
void udp_send_file(int s, struct sockaddr*to, int fd, int package_length)
{
	char buff_init[LENGTH];			/*发送给服务器的测试数据05	*/
	struct sockaddr_in from;					/*服务器地址*/
	// 包索引值
	int i = 0;
	socklen_t len = sizeof(*to);					/*地址长度*/
	struct timeval start;
	int user_id;
    gettimeofday( &start, NULL);
	// 用户id为随机取的值
	user_id = (start.tv_sec * 100 + start.tv_usec * 100 * 1000) % 100000000;

	// 第一个包用来发送长度
	memset(buff_init, '\0', sizeof(buff_init));
	printf("package length: %d\n", package_length);
	wrapper_data(i, package_length, user_id, buff_init);
	sendto(s, &buff_send[0], SEND_LENGTH, 0, to, len);		/*发送给服务器*/
	i++;
	
	while (1)
	{
		memset(buff_init, '\0', sizeof(buff_init));
		memset(buff_send, '\0', sizeof(buff_send));
		ssize_t size = read(fd, buff_init, LENGTH);
		if ((int) size <= 0) 
		{
			wrapper_data(i, 1, user_id, buff_init);
			sendto(s, &buff_send[0], SEND_LENGTH, 0, to, len);		/*发送给服务器*/
			printf("\n一共发送%d个包(一个开始包，一个结束包) userId: %d \n", i + 1, user_id);
			exit(0);
		}
		wrapper_data(i, 0, user_id, buff_init);
		sendto(s, &buff_send[0], SEND_LENGTH, 0, to, len);		/*发送给服务器*/
		i++;
		// 延迟100us 避免服务器接收不过来
		usleep(10);
	}
} 

/**
 * 获取文件大小
*/
int file_size(char *fileName)
{
	struct stat statbuf;
	stat(fileName, &statbuf);
	int size = statbuf.st_size;
	return size;
}


int main(int argc, char*argv[])
{
	int s;											/*套接字文件描述符*/
	struct sockaddr_in addr_serv;					/*地址结构*/
	// 一个包长度1k, 一般不会除尽会有小数，所以加1
	int package_length = file_size(argv[1]) / 1024 + 1;

	int fd = open(argv[1], O_RDONLY);
	if (fd == -1)
	{
		printf("open file error\n");
		return 0;
	}
	
	s = socket(AF_INET, SOCK_DGRAM, 0);			/*建立数据报套接字*/
	
	memset(&addr_serv, 0, sizeof(addr_serv));		/*清空地址结构*/
	addr_serv.sin_family = AF_INET;				/*地址类型为AF_INET*/
	addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);	/*任意本地地址*/
	addr_serv.sin_port = htons(PORT_SERV);			/*服务器端口*/
	
	udp_send_file(s, (struct sockaddr*)&addr_serv, fd, package_length);	/*客户端回显程序*/
	
	close(s);
	return 0;	
}
